package com.franklin.ideaplugin.easytesting.controllerclient.support;

import com.franklin.ideaplugin.easytesting.controllerclient.MethodBuilder;
import com.franklin.ideaplugin.easytesting.controllerclient.NotAnnotatedParameterProcessor;
import com.franklin.ideaplugin.easytesting.controllerclient.annotation.*;
import com.franklin.ideaplugin.easytesting.controllerclient.client.DefaultControllerClientBuilder;
import com.franklin.ideaplugin.easytesting.controllerclient.client.IControllerClientBuilder;
import com.franklin.ideaplugin.easytesting.controllerclient.request.DefaultRequestBuilder;
import com.franklin.ideaplugin.easytesting.controllerclient.request.IRequestBuilder;
import com.franklin.ideaplugin.easytesting.controllerclient.request.IRequestInvoker;
import com.franklin.ideaplugin.easytesting.controllerclient.request.OkHttpRequestInvoker;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PreDestroy;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

/**
 * @author Ye Junhui
 * @since 2023/6/29
 */
@Configuration
public class ControllerClientAutoConfiguration {

    @Bean
    public ControllerClientRegistrar easyTestingControllerClientRegistrar(){
        return new ControllerClientRegistrar();
    }

    @Bean
    public MethodBuilder easyTestingMethodBuilder(){
        return new MethodBuilder(
                Arrays.asList(
                        new HeaderParameterProcessor(),
                        new PathParameterProcessor(),
                        new RequestBodyParameterProcessor(),
                        new RequestParamParameterProcessor(),
                        new RequestPartParameterProcessor(),
                        new NotAnnotatedParameterProcessor()
                )
        );
    }

    @Bean
    public IRequestBuilder easyTestingRequestBuilder(){
        return new DefaultRequestBuilder();
    }

    @Bean
    @Autowired
    public IRequestInvoker easyTestingRequestInvoker(
            OkHttpClient okHttpClient
    ){
        return new OkHttpRequestInvoker(okHttpClient);
    }

    @Bean
    @Autowired
    public IControllerClientBuilder easyTestingControllerClientBuilder(
            MethodBuilder methodBuilder,
            IRequestBuilder requestBuilder,
            IRequestInvoker requestInvoker
    ){
        return new DefaultControllerClientBuilder(methodBuilder,requestBuilder,requestInvoker);
    }


    @Configuration(proxyBeanMethods = false)
    @ConditionalOnClass(OkHttpClient.class)
    @ConditionalOnMissingBean(okhttp3.OkHttpClient.class)
    public static class EasyTestingOkHttpFeignConfiguration {

        private okhttp3.OkHttpClient okHttpClient;

        @Bean
        @ConditionalOnMissingBean(ConnectionPool.class)
        public ConnectionPool easyTestingHttpClientConnectionPool() {
            return new ConnectionPool();
        }

        @Bean
        public okhttp3.OkHttpClient easyTestingClient(
                ConnectionPool connectionPool) {
            this.okHttpClient = new okhttp3.OkHttpClient.Builder()
                    .callTimeout(2, TimeUnit.MINUTES)
                    .readTimeout(2,TimeUnit.MINUTES)
                    .connectionPool(connectionPool).build();
            return this.okHttpClient;
        }

        @PreDestroy
        public void destroy() {
            if (this.okHttpClient != null) {
                this.okHttpClient.dispatcher().executorService().shutdown();
                this.okHttpClient.connectionPool().evictAll();
            }
        }

    }
}
